package cn.jbolt.core.enjoy.directive;

import cn.jbolt.core.util.JBoltArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.jfinal.kit.StrKit;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;

import java.io.IOException;
import java.util.Set;

/**
 * 专门处理数据转JSON的指令
 *
 * @ClassName: JsonDirective
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2021年01月07日
 */
public class JsonDirective extends Directive {

	private Expr valueExpr;
	private Expr filterColumnExpr;
	private Expr datePatternExpr;
	private int paraNum;

	@Override
	public void setExprList(ExprList exprList) {
		this.paraNum = exprList.length();
		if (paraNum == 0) {
			throw new ParseException("Wrong number parameter of #json directive, one parameters allowed at most",
					location);
		} else if (paraNum > 3) {
			throw new ParseException("Wrong number parameter of #json directive, three parameters allowed at most",
					location);
		}

		if (paraNum == 1) {
			this.valueExpr = exprList.getExpr(0);
			this.filterColumnExpr = null;
		} else if (paraNum == 2) {
			this.valueExpr = exprList.getExpr(0);
			this.filterColumnExpr = exprList.getExpr(1);
		} else if (paraNum == 3) {
			this.valueExpr = exprList.getExpr(0);
			this.filterColumnExpr = exprList.getExpr(1);
			this.datePatternExpr = exprList.getExpr(2);
		}

		if (this.valueExpr == null) {
			throw new ParseException("the first parameter of #json directive cannot be null", location);
		}
	}

	@Override
	public void exec(Env env, Scope scope, Writer writer) {
		Object jsonObj = this.valueExpr.eval(scope);
		if (jsonObj != null) {
			String dp = defaultDatePattern;
			if(datePatternExpr!=null){
				Object datePattern = datePatternExpr.eval(scope);
				if(datePattern!=null){
					dp = datePattern.toString();
				}
			}
			try {
				if (this.filterColumnExpr == null) {
					writer.write(objectToJson(jsonObj,dp));
				} else {
					Object filterColumn = this.filterColumnExpr.eval(scope);
					if (filterColumn == null) {
						writer.write(objectToJson(jsonObj,dp));
					} else {
						String fcs = filterColumn.toString();
						if (StrKit.isBlank(fcs)) {
							writer.write(objectToJson(jsonObj,dp));
						} else {
							String[] columns = JBoltArrayUtil.from2(fcs, ",");
							if (columns != null && columns.length > 0) {
								writer.write(objectToJson(jsonObj, columns,dp));
							}
						}

					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}
	private static String defaultDatePattern = "yyyy-MM-dd HH:mm:ss";	//
	public String objectToJson(Object obj,String datePattern) {
		return JSON.toJSONStringWithDateFormat(obj,StrKit.defaultIfBlank(datePattern,defaultDatePattern), SerializerFeature.DisableCircularReferenceDetect);
	}

	public String objectToJson(Object obj, String[] columns,String datePattern) {
		// 属性过滤器对象
		SimplePropertyPreFilter filter = new SimplePropertyPreFilter();

		// 属性排斥集合,强调某些属性不需要或者一定不能被序列化
		Set<String> includes = filter.getIncludes();

		// 排除不需序列化的属性
		for (String column : columns) {
			includes.add(column);
		}

		// 调用fastJson的方法,对象转json,
		// 参数一:需要被序列化的对象
		// 参数二:用于过滤属性的过滤器
		// 参数三:关闭循环引用,若不加这个,页面无法展示重复的属性值
		return JSON.toJSONString(obj, SerializeConfig.globalInstance,new SerializeFilter[] {filter} , StrKit.defaultIfBlank(datePattern,defaultDatePattern), JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.DisableCircularReferenceDetect);
	}

}
